﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using FA.FlightAttendant.ViewModel.Windows;
using FA.FlightAttendant.Plugin;
using FA.FlightAttendant.Properties;
using System.IO;
using NLog;
using System.Windows;
using FA.Library.Plugin;
using FA.FlightAttendant.Host;

namespace FA.FlightAttendant.View.Commands
{
    public class SubmitNewSimulatorCommand : ICommand
    {
        private static readonly Logger _logger = LogManager.GetCurrentClassLogger();

        private NewSimulatorVM _viewModel;

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public SubmitNewSimulatorCommand(NewSimulatorVM viewModel)
        {
            _viewModel = viewModel;
        }

        public void Execute(object parameter)
        {
            NewSimulatorInfo simInfo = (NewSimulatorInfo)parameter;

            // Check if the simulator name is unique
            if (!simInfo.Name.Equals(simInfo.OriginalName))
            {
                // If the name already exists, prompt the user to pick a new one
                if (SimHost.Instance.ManagesSimulator(simInfo.Name))
                {
                    MessageBox.Show("A simulator already exists with this name.");
                    return;
                }
            }

            bool? dialogResult = null;
            try
            {
                // Update the SimHost singleton
                updateSimHost(simInfo);

                // Set dialogresult to true since it isn't imperative that the XML be updated
                dialogResult = true;

                try
                {
                    // Update the XML file
                    updateXML(simInfo);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Unable to save simulator to XML", ex);
                    MessageBox.Show(
                        "Unable to save simulator to XML.\n\n" + ex.Message,
                        "Unable to save simulator",
                        MessageBoxButton.OK,
                        MessageBoxImage.Warning);
                }
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Unable to create simulator.", ex);
                MessageBox.Show(
                    "Unable to create simulator.\n\n" + ex.Message,
                    "Unable to create simulator",
                    MessageBoxButton.OK,
                    MessageBoxImage.Warning);
            }

            // Update the dialog result (when this is non-null the window will close)
            _viewModel.DialogResult = dialogResult;
        }

        public bool CanExecute(object parameter)
        {
            return (parameter != null && (parameter is NewSimulatorInfo) && (parameter as NewSimulatorInfo).FieldsArePopulated());
        }

        /// <summary>
        /// Update the SimHost singleton with the new simulator info.
        /// </summary>
        /// <param name="simInfo"></param>
        private void updateSimHost(NewSimulatorInfo simInfo)
        {
            // Instantiate the Plugin class
            IPlugin plugin = PluginFactory.Instance.CreatePlugin(simInfo.Plugin.Classname);

            // Set the name of the plugin
            plugin.Name = simInfo.Name;

            // Set the settings on the plugin
            plugin.UpdateSettings(PluginSetting.ConvertToDictionary(simInfo.Settings));

            // Create the simulator wrapper for the plugin
            Simulator simulator = new Simulator(plugin);

            // If we were editing an existing simulator, unregister the previous version
            if (!String.IsNullOrEmpty(simInfo.OriginalName))
                SimHost.Instance.UnregisterSimulator(simInfo.OriginalName, true);

            // Register the simulator
            SimHost.Instance.RegisterSimulator(simulator);
        }

        /// <summary>
        /// Write the new or edited simulator info to the simulators XML file.
        /// </summary>
        /// <param name="simInfo"></param>
        private void updateXML(NewSimulatorInfo simInfo)
        {
            string simulatorFile = Path.Combine(Environment.CurrentDirectory, Settings.Default.SimulatorsFile);
            SimulatorFileWriter simFileWriter = new SimulatorFileWriter(simulatorFile);

            // Check if this is a new simulator or if we're changing an existing one
            if (String.IsNullOrEmpty(simInfo.OriginalName))
            {
                simFileWriter.AddSimulator(
                    simInfo.Plugin.Classname,
                    simInfo.Name,
                    PluginSetting.ConvertToDictionary(simInfo.Settings));
            }
            else
            {
                simFileWriter.EditSimulator(
                    simInfo.OriginalName,
                    simInfo.Plugin.Classname,
                    simInfo.Name,
                    PluginSetting.ConvertToDictionary(simInfo.Settings));
            }
        }
    }
}